#include "pch.hpp"
#include "ProjectExplorer.hpp"

#include "Script.hpp"
#include "UiDefinition.hpp"

using namespace Engine;
using namespace Engine::Edit;




ProjectExplorer::ProjectExplorer(QWidget* parent)
	: QWidget(parent)
	, m_state(State::Idle)
{
	ui.setupUi(this);

	ui.projectView->setContextMenuPolicy(Qt::CustomContextMenu);

	verify(connect(ui.projectView, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(onContextMenuRequested(const QPoint&))));
	verify(connect(ui.projectView, SIGNAL(doubleClicked(const QModelIndex&)), SLOT(onDoubleClicked(const QModelIndex&))));

	verify(connect(ui.actionRemove_Script, SIGNAL(activated()), SLOT(removeSelectedItems())));
	verify(connect(ui.actionRemove_Ui, SIGNAL(activated()), SLOT(removeSelectedItems())));
}
///////////////////////////////////////////////////////////////////////////////////////////////////

ProjectExplorer::~ProjectExplorer()
{}
///////////////////////////////////////////////////////////////////////////////////////////////////




void ProjectExplorer::setProject(Project::ptr project)
{
	ui.projectView->setModel(nullptr);
	m_test.reset();
	m_model.reset();
	m_project.reset();

	if(project)
	{
		m_project = project;
		m_model = boost::make_shared<ProjectModel>(project);
		m_test = boost::make_shared<ModelTest>(m_model.get());

		ui.projectView->setModel(m_model.get());
		ui.projectView->expandAll();

		auto m = ui.projectView->selectionModel();

		verify(connect(ui.projectView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
						this, SLOT(onSelectionChanged(const QItemSelection&, const QItemSelection&))));
		/*verify(connect(ui.projectView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
						this, SLOT(onSelectionChanged())));*/
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void ProjectExplorer::changeState(State::Type state)
{
	m_state = state;
}
///////////////////////////////////////////////////////////////////////////////////////////////////




void ProjectExplorer::ensureVisible(ProjectItem::ptr item)
{
	// Make sure the item is visible in the project tree
	auto index = m_model->indexFromItem(item);
	ui.projectView->scrollTo(index, QAbstractItemView::EnsureVisible);
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void ProjectExplorer::select(ProjectItem::ptr item, QItemSelectionModel::SelectionFlags flags)
{
	// Make sure the item is selected in the project tree
	auto index = m_model->indexFromItem(item);
	ui.projectView->selectionModel()->select(index, flags);
}
///////////////////////////////////////////////////////////////////////////////////////////////////

ProjectItem::ptr ProjectExplorer::item(SpecialItem where) const
{
	switch(where)
	{
	case Project:       return m_project;
	case Scripts:       return m_project->child("Scripts");
	case UiDefinitions: return m_project->child("Ui Definitions");
	case Materials:     return m_project->child("Materials");
	case Meshes:        return m_project->child("Meshes");
	default: throw invalid_value_exception(where);
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////




void ProjectExplorer::onContextMenuRequested(const QPoint& point)
{
	if(m_state != State::Editing)
		return;

	auto index = ui.projectView->indexAt(point);
	if(!index.isValid())
		return;

	auto item = m_model->itemFromIndex(index);
	if(!item)
		return;

	QMenu* menu = nullptr;
	if(boost::shared_dynamic_cast<Script>(item))
	{
		menu = new QMenu(ui.projectView);
		menu->addAction(ui.actionRemove_Script);
	}
	else if(boost::shared_dynamic_cast<UiDefinition>(item))
	{
		menu = new QMenu(ui.projectView);
		menu->addAction(ui.actionRemove_Ui);
	}

	if(menu)
		menu->exec(ui.projectView->mapToGlobal(point));
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void ProjectExplorer::onSelectionChanged(const QItemSelection& selected, const QItemSelection& unselected)
{
	emit this->selected(items(selected), items(unselected));
}
/*void ProjectExplorer::onSelectionChanged()
{
	auto index = ui.projectView->selectionModel()->currentIndex();
	if(!index.isValid())
		return;

	emit selected(m_model->itemFromIndex(index));
}*/
///////////////////////////////////////////////////////////////////////////////////////////////////

void ProjectExplorer::onDoubleClicked(const QModelIndex& index)
{
	auto item = m_model->itemFromIndex(index);
	if(!item)
		return;

	emit doubleClicked(item);
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void ProjectExplorer::removeSelectedItems()
{
	if(m_state != State::Editing)
		return;

	auto index = ui.projectView->selectionModel()->currentIndex();
	if(!index.isValid())
		return;

	auto item = m_model->itemFromIndex(index);
	if(!item)
		return;

	auto parent = item->parent();
	if(!parent)
		return;

	auto selectedItems = items(ui.projectView->selectionModel()->selection());
	foreach(ProjectItem::ptr item, selectedItems)
	{
		auto parent = item->parent();
		if(!parent)
			return;

		parent->remove(item);
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////




QList<ProjectItem::ptr> ProjectExplorer::items(const QItemSelection& selection) const
{
	QList<ProjectItem::ptr> items;

	foreach(const QItemSelectionRange& range, selection)
	{
		foreach(const QModelIndex& index, range.indexes())
		{
			auto item = m_model->itemFromIndex(index);
			if(item)
				items << item;
		}
	}

	return items;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
